/*
 * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
 *
 * (c) Copyright 1996 - 2001 Gary Henderson (gary@daniver.demon.co.uk) and
 *                           Jerremy Koot (jkoot@snes9x.com)
 *
 * Super FX C emulator code 
 * (c) Copyright 1997 - 1999 Ivar (Ivar@snes9x.com) and
 *                           Gary Henderson.
 * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
 *
 * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
 * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
 * C4 C code (c) Copyright 2001 Gary Henderson (gary@daniver.demon.co.uk).
 *
 * DOS port code contains the works of other authors. See headers in
 * individual files.
 *
 * Snes9x homepage: www.snes9x.com
 *
 * Permission to use, copy, modify and distribute Snes9x in both binary and
 * source form, for non-commercial purposes, is hereby granted without fee,
 * providing that this license information and copyright notice appear with
 * all copies and any derived work.
 *
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event shall the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Snes9x is freeware for PERSONAL USE only. Commercial users should
 * seek permission of the copyright holders first. Commercial use includes
 * charging money for Snes9x or software derived from Snes9x.
 *
 * The copyright holders request that bug fixes and improvements to the code
 * should be forwarded to them so everyone can benefit from the modifications
 * in future versions.
 *
 * Super NES and Super Nintendo Entertainment System are trademarks of
 * Nintendo Co., Limited and its subsidiary companies.
 */
#include "types.h"
#include "2xSaI.h"

#define USE_COLOR_MODE  1   //0:var, 1:RGB565, 2:RGB555

#if USE_COLOR_MODE == 1
#define colorMask       0xF7DEF7DE
#define lowPixelMask    0x08210821
#define qcolorMask      0xE79CE79C
#define qlowpixelMask   0x18631863
#define redblueMask     0xF81F
#define greenMask       0x7E0
int Init_2xSaI(u32 BitFormat)
{
    return BitFormat == 565 ? 1 : 0;
}
#elif USE_COLOR_MODE == 2
#define colorMask       0x7BDE7BDE
#define lowPixelMask    0x04210421
#define qcolorMask      0x739C739C
#define qlowpixelMask   0x0C630C63
#define redblueMask     0x7C1F
#define greenMask       0x3E0
int Init_2xSaI(u32 BitFormat)
{
    return BitFormat == 555 ? 1 : 0;
}
#else
static u32 colorMask = 0xF7DEF7DE;
static u32 lowPixelMask = 0x08210821;
static u32 qcolorMask = 0xE79CE79C;
static u32 qlowpixelMask = 0x18631863;
static u32 redblueMask = 0xF81F;
static u32 greenMask = 0x7E0;

int Init_2xSaI(u32 BitFormat)
{
  if (BitFormat == 565) {
    colorMask = 0xF7DEF7DE;
    lowPixelMask = 0x08210821;
    qcolorMask = 0xE79CE79C;
    qlowpixelMask = 0x18631863;
    redblueMask = 0xF81F;
    greenMask = 0x7E0;
  } else if (BitFormat == 555) {
    colorMask = 0x7BDE7BDE;
    lowPixelMask = 0x04210421;
    qcolorMask = 0x739C739C;
    qlowpixelMask = 0x0C630C63;
    redblueMask = 0x7C1F;
    greenMask = 0x3E0;
  } else {
    return 0;
  }

  return 1;
}
#endif


static inline int GetResult1 (u32 A, u32 B, u32 C, u32 D,
			      u32 /* E */)
{
    int x = 0;
    int y = 0;
    int r = 0;

    if (A == C)
      x += 1;
    else if (B == C)
      y += 1;
    if (A == D)
      x += 1;
    else if (B == D)
      y += 1;
    if (x <= 1)
      r += 1;
    if (y <= 1)
      r -= 1;
    return r;
}

static inline int GetResult2 (u32 A, u32 B, u32 C, u32 D,
			      u32 /* E */)
{
  int x = 0;
  int y = 0;
  int r = 0;
  
  if (A == C)
    x += 1;
  else if (B == C)
    y += 1;
  if (A == D)
    x += 1;
  else if (B == D)
    y += 1;
  if (x <= 1)
    r -= 1;
  if (y <= 1)
    r += 1;
  return r;
}

static inline int GetResult (u32 A, u32 B, u32 C, u32 D)
{
  int x = 0;
  int y = 0;
  int r = 0;
  
  if (A == C)
    x += 1;
  else if (B == C)
    y += 1;
  if (A == D)
    x += 1;
  else if (B == D)
    y += 1;
  if (x <= 1)
    r += 1;
  if (y <= 1)
    r -= 1;
  return r;
}

static inline u32 INTERPOLATE (u32 A, u32 B)
{
  if (A != B) {
    return (((A & colorMask) >> 1) + ((B & colorMask) >> 1) +
	    (A & B & lowPixelMask));
  } else
    return A;
}

static inline u32 Q_INTERPOLATE (u32 A, u32 B, u32 C, u32 D)
{
  register u32 x = ((A & qcolorMask) >> 2) +
    ((B & qcolorMask) >> 2) +
    ((C & qcolorMask) >> 2) + ((D & qcolorMask) >> 2);
  register u32 y = (A & qlowpixelMask) +
    (B & qlowpixelMask) + (C & qlowpixelMask) + (D & qlowpixelMask);
  
  y = (y >> 2) & qlowpixelMask;
  return x + y;
}

#define BLUE_MASK565 0x001F001F
#define RED_MASK565 0xF800F800
#define GREEN_MASK565 0x07E007E0

#define BLUE_MASK555 0x001F001F
#define RED_MASK555 0x7C007C00
#define GREEN_MASK555 0x03E003E0

void Super2xSaI (u8 *srcPtr, u32 srcPitch,
		 u8 *deltaPtr, u8 *dstPtr, u32 dstPitch,
		 int width, int height)
{
    u16 *bP;
    u8  *dP;
    u32 inc_bP;
    u32 Nextline = srcPitch >> 1;

    {
      inc_bP = 1;
      
      for (; height; height--) {
	bP = (u16 *) srcPtr;
	dP = (u8 *) dstPtr;
	
	for (u32 finish = width; finish; finish -= inc_bP) {
	  u32 color4, color5, color6;
	  u32 color1, color2, color3;
	  u32 colorA0, colorA1, colorA2, colorA3,
	    colorB0, colorB1, colorB2, colorB3, colorS1, colorS2;
	  u32 product1a, product1b, product2a, product2b;
	  
	  //---------------------------------------    B1 B2
	  //                                         4  5  6 S2
	  //                                         1  2  3 S1
	  //                                           A1 A2
	  
	  colorB0 = *(bP - Nextline - 1);
	  colorB1 = *(bP - Nextline);
	  colorB2 = *(bP - Nextline + 1);
	  colorB3 = *(bP - Nextline + 2);
	  
	  color4 = *(bP - 1);
	  color5 = *(bP);
	  color6 = *(bP + 1);
	  colorS2 = *(bP + 2);
	  
	  color1 = *(bP + Nextline - 1);
	  color2 = *(bP + Nextline);
	  color3 = *(bP + Nextline + 1);
	  colorS1 = *(bP + Nextline + 2);
	  
	  colorA0 = *(bP + Nextline + Nextline - 1);
	  colorA1 = *(bP + Nextline + Nextline);
	  colorA2 = *(bP + Nextline + Nextline + 1);
	  colorA3 = *(bP + Nextline + Nextline + 2);
	  
	  //--------------------------------------
	  if (color2 == color6 && color5 != color3) {
	    product2b = product1b = color2;
	  } else if (color5 == color3 && color2 != color6) {
	    product2b = product1b = color5;
	  } else if (color5 == color3 && color2 == color6) {
	    register int r = 0;
	    
	    r += GetResult (color6, color5, color1, colorA1);
	    r += GetResult (color6, color5, color4, colorB1);
	    r += GetResult (color6, color5, colorA2, colorS1);
	    r += GetResult (color6, color5, colorB2, colorS2);
	    
	    if (r > 0)
	      product2b = product1b = color6;
	    else if (r < 0)
	      product2b = product1b = color5;
	    else {
	      product2b = product1b = INTERPOLATE (color5, color6);
	    }
	  } else {
	    if (color6 == color3 && color3 == colorA1
		&& color2 != colorA2 && color3 != colorA0)
	      product2b =
		Q_INTERPOLATE (color3, color3, color3, color2);
	    else if (color5 == color2 && color2 == colorA2
		     && colorA1 != color3 && color2 != colorA3)
	      product2b =
		Q_INTERPOLATE (color2, color2, color2, color3);
	    else
	      product2b = INTERPOLATE (color2, color3);
	    
	    if (color6 == color3 && color6 == colorB1
		&& color5 != colorB2 && color6 != colorB0)
	      product1b =
		Q_INTERPOLATE (color6, color6, color6, color5);
	    else if (color5 == color2 && color5 == colorB2
		     && colorB1 != color6 && color5 != colorB3)
	      product1b =
		Q_INTERPOLATE (color6, color5, color5, color5);
	    else
	      product1b = INTERPOLATE (color5, color6);
	  }
	  
	  if (color5 == color3 && color2 != color6 && color4 == color5
	      && color5 != colorA2)
	    product2a = INTERPOLATE (color2, color5);
	  else
	    if (color5 == color1 && color6 == color5
		&& color4 != color2 && color5 != colorA0)
	      product2a = INTERPOLATE (color2, color5);
	    else
	      product2a = color2;
	  
	  if (color2 == color6 && color5 != color3 && color1 == color2
	      && color2 != colorB2)
	    product1a = INTERPOLATE (color2, color5);
	  else
	    if (color4 == color2 && color3 == color2
		&& color1 != color5 && color2 != colorB0)
	      product1a = INTERPOLATE (color2, color5);
	    else
	      product1a = color5;
	  
	  product1a = product1a | (product1b << 16);
	  product2a = product2a | (product2b << 16);
	  
	  *((u32 *) dP) = product1a;
	  *((u32 *) (dP + dstPitch)) = product2a;
	  
	  bP += inc_bP;
	  dP += sizeof (u32);
	}			// end of for ( finish= width etc..)
	
	srcPtr   += srcPitch;
	dstPtr   += dstPitch * 2;
//	deltaPtr += srcPitch;
      }			// endof: for (; height; height--)
    }
}

void SuperEagle (u8 *srcPtr, u32 srcPitch, u8 *deltaPtr, 
		 u8 *dstPtr, u32 dstPitch, int width, int height)
{
  u8  *dP;
  u16 *bP;
  u16 *xP;
  u32 inc_bP;

  {
    inc_bP = 1;
    
    u32 Nextline = srcPitch >> 1;
    
    for (; height; height--) {
      bP = (u16 *) srcPtr;
//      xP = (u16 *) deltaPtr;
      dP = dstPtr;
      for (u32 finish = width; finish; finish -= inc_bP) {
	u32 color4, color5, color6;
	u32 color1, color2, color3;
	u32 colorA1, colorA2, colorB1, colorB2, colorS1, colorS2;
	u32 product1a, product1b, product2a, product2b;
	
	colorB1 = *(bP - Nextline);
	colorB2 = *(bP - Nextline + 1);
	
	color4 = *(bP - 1);
	color5 = *(bP);
	color6 = *(bP + 1);
	colorS2 = *(bP + 2);
	
	color1 = *(bP + Nextline - 1);
	color2 = *(bP + Nextline);
	color3 = *(bP + Nextline + 1);
	colorS1 = *(bP + Nextline + 2);
	
	colorA1 = *(bP + Nextline + Nextline);
	colorA2 = *(bP + Nextline + Nextline + 1);
	
	// --------------------------------------
	if (color2 == color6 && color5 != color3) {
	  product1b = product2a = color2;
	  if ((color1 == color2) || (color6 == colorB2)) {
	    product1a = INTERPOLATE (color2, color5);
	    product1a = INTERPOLATE (color2, product1a);
	    //                       product1a = color2;
	  } else {
	    product1a = INTERPOLATE (color5, color6);
	  }
	  
	  if ((color6 == colorS2) || (color2 == colorA1)) {
	    product2b = INTERPOLATE (color2, color3);
	    product2b = INTERPOLATE (color2, product2b);
	    //                       product2b = color2;
	  } else {
	    product2b = INTERPOLATE (color2, color3);
	  }
	} else if (color5 == color3 && color2 != color6) {
	  product2b = product1a = color5;
	  
	  if ((colorB1 == color5) || (color3 == colorS1)) {
	    product1b = INTERPOLATE (color5, color6);
	    product1b = INTERPOLATE (color5, product1b);
	    //                       product1b = color5;
	  } else {
	    product1b = INTERPOLATE (color5, color6);
	  }
	  
	  if ((color3 == colorA2) || (color4 == color5)) {
	    product2a = INTERPOLATE (color5, color2);
	    product2a = INTERPOLATE (color5, product2a);
	    //                       product2a = color5;
	  } else {
	    product2a = INTERPOLATE (color2, color3);
	  }
	  
	} else if (color5 == color3 && color2 == color6) {
	  register int r = 0;
	  
	  r += GetResult (color6, color5, color1, colorA1);
	  r += GetResult (color6, color5, color4, colorB1);
	  r += GetResult (color6, color5, colorA2, colorS1);
	  r += GetResult (color6, color5, colorB2, colorS2);
	  
	  if (r > 0) {
	    product1b = product2a = color2;
	    product1a = product2b = INTERPOLATE (color5, color6);
	  } else if (r < 0) {
	    product2b = product1a = color5;
	    product1b = product2a = INTERPOLATE (color5, color6);
	  } else {
	    product2b = product1a = color5;
	    product1b = product2a = color2;
	  }
	} else {
	  product2b = product1a = INTERPOLATE (color2, color6);
	  product2b =
	    Q_INTERPOLATE (color3, color3, color3, product2b);
	  product1a =
	    Q_INTERPOLATE (color5, color5, color5, product1a);
	  
	  product2a = product1b = INTERPOLATE (color5, color3);
	  product2a =
	    Q_INTERPOLATE (color2, color2, color2, product2a);
	  product1b =
	    Q_INTERPOLATE (color6, color6, color6, product1b);
	  
	  //                    product1a = color5;
	  //                    product1b = color6;
	  //                    product2a = color2;
	  //                    product2b = color3;
	}
	product1a = product1a | (product1b << 16);
	product2a = product2a | (product2b << 16);
	
	*((u32 *) dP) = product1a;
	*((u32 *) (dP + dstPitch)) = product2a;
//	*xP = color5;
	
	bP += inc_bP;
//	xP += inc_bP;
	dP += sizeof (u32);
      }			// end of for ( finish= width etc..)
      
      srcPtr += srcPitch;
      dstPtr += dstPitch * 2;
//      deltaPtr += srcPitch;
    }			// endof: for (height; height; height--)
  }
}

void _2xSaI (u8 *srcPtr, u32 srcPitch, u8 *deltaPtr,
	     u8 *dstPtr, u32 dstPitch, int width, int height)
{
  u8  *dP;
  u16 *bP;
  u32 inc_bP;
  
  {
    inc_bP = 1;
    
    u32 Nextline = srcPitch >> 1;
    
    for (; height; height--) {
      bP = (u16 *) srcPtr;
      dP = dstPtr;
      
      for (u32 finish = width; finish; finish -= inc_bP) {
	
	register u32 colorA, colorB;
	u32 colorC, colorD,
	  colorE, colorF, colorG, colorH,
	  colorI, colorJ, colorK, colorL,
	  
	  colorM, colorN, colorO, colorP;
	u32 product, product1, product2;
	
	//---------------------------------------
	// Map of the pixels:                    I|E F|J
	//                                       G|A B|K
	//                                       H|C D|L
	//                                       M|N O|P
	colorI = *(bP - Nextline - 1);
	colorE = *(bP - Nextline);
	colorF = *(bP - Nextline + 1);
	colorJ = *(bP - Nextline + 2);
	
	colorG = *(bP - 1);
	colorA = *(bP);
	colorB = *(bP + 1);
	colorK = *(bP + 2);
	
	colorH = *(bP + Nextline - 1);
	colorC = *(bP + Nextline);
	colorD = *(bP + Nextline + 1);
	colorL = *(bP + Nextline + 2);
	
	colorM = *(bP + Nextline + Nextline - 1);
	colorN = *(bP + Nextline + Nextline);
	colorO = *(bP + Nextline + Nextline + 1);
	colorP = *(bP + Nextline + Nextline + 2);
	
	if ((colorA == colorD) && (colorB != colorC)) {
	  if (((colorA == colorE) && (colorB == colorL)) ||
	      ((colorA == colorC) && (colorA == colorF)
	       && (colorB != colorE) && (colorB == colorJ))) {
	    product = colorA;
	  } else {
	    product = INTERPOLATE (colorA, colorB);
	  }
	  
	  if (((colorA == colorG) && (colorC == colorO)) ||
	      ((colorA == colorB) && (colorA == colorH)
	       && (colorG != colorC) && (colorC == colorM))) {
	    product1 = colorA;
	  } else {
	    product1 = INTERPOLATE (colorA, colorC);
	  }
	  product2 = colorA;
	} else if ((colorB == colorC) && (colorA != colorD)) {
	  if (((colorB == colorF) && (colorA == colorH)) ||
	      ((colorB == colorE) && (colorB == colorD)
	       && (colorA != colorF) && (colorA == colorI))) {
	    product = colorB;
	  } else {
	    product = INTERPOLATE (colorA, colorB);
	  }
	  
	  if (((colorC == colorH) && (colorA == colorF)) ||
	      ((colorC == colorG) && (colorC == colorD)
	       && (colorA != colorH) && (colorA == colorI))) {
	    product1 = colorC;
	  } else {
	    product1 = INTERPOLATE (colorA, colorC);
	  }
	  product2 = colorB;
	} else if ((colorA == colorD) && (colorB == colorC)) {
	  if (colorA == colorB) {
	    product = colorA;
	    product1 = colorA;
	    product2 = colorA;
	  } else {
	    register int r = 0;
	    
	    product1 = INTERPOLATE (colorA, colorC);
	    product = INTERPOLATE (colorA, colorB);
	    
	    r +=
	      GetResult1 (colorA, colorB, colorG, colorE,
			  colorI);
	    r +=
	      GetResult2 (colorB, colorA, colorK, colorF,
			  colorJ);
	    r +=
	      GetResult2 (colorB, colorA, colorH, colorN,
			  colorM);
	    r +=
	      GetResult1 (colorA, colorB, colorL, colorO,
			  colorP);
	    
	    if (r > 0)
	      product2 = colorA;
	    else if (r < 0)
	      product2 = colorB;
	    else {
	      product2 =
		Q_INTERPOLATE (colorA, colorB, colorC,
			       colorD);
	    }
	  }
	} else {
	  product2 = Q_INTERPOLATE (colorA, colorB, colorC, colorD);
	  
	  if ((colorA == colorC) && (colorA == colorF)
	      && (colorB != colorE) && (colorB == colorJ)) {
	    product = colorA;
	  } else if ((colorB == colorE) && (colorB == colorD)
		     && (colorA != colorF) && (colorA == colorI)) {
	    product = colorB;
	  } else {
	    product = INTERPOLATE (colorA, colorB);
	  }
	  
	  if ((colorA == colorB) && (colorA == colorH)
	      && (colorG != colorC) && (colorC == colorM)) {
	    product1 = colorA;
	  } else if ((colorC == colorG) && (colorC == colorD)
		     && (colorA != colorH) && (colorA == colorI)) {
	    product1 = colorC;
	  } else {
	    product1 = INTERPOLATE (colorA, colorC);
	  }
	}
	
	product = colorA | (product << 16);
	product1 = product1 | (product2 << 16);
	*((s32 *) dP) = product;
	*((u32 *) (dP + dstPitch)) = product1;
	
	bP += inc_bP;
	dP += sizeof (u32);
      }			// end of for ( finish= width etc..)
      
      srcPtr += srcPitch;
      dstPtr += dstPitch * 2;
//      deltaPtr += srcPitch;
    }			// endof: for (height; height; height--)
  }
}

static u32 Bilinear (u32 A, u32 B, u32 x)
{
  unsigned long areaA, areaB;
  unsigned long result;
  
  if (A == B)
    return A;
  
  areaB = (x >> 11) & 0x1f;	// reduce 16 bit fraction to 5 bits
  areaA = 0x20 - areaB;
  
  A = (A & redblueMask) | ((A & greenMask) << 16);
  B = (B & redblueMask) | ((B & greenMask) << 16);
  
  result = ((areaA * A) + (areaB * B)) >> 5;
  
  return (result & redblueMask) | ((result >> 16) & greenMask);
}

static u32 Bilinear4 (u32 A, u32 B, u32 C, u32 D, u32 x,
			 u32 y)
{
  unsigned long areaA, areaB, areaC, areaD;
  unsigned long result, xy;
  
  x = (x >> 11) & 0x1f;
  y = (y >> 11) & 0x1f;
  xy = (x * y) >> 5;
  
  A = (A & redblueMask) | ((A & greenMask) << 16);
  B = (B & redblueMask) | ((B & greenMask) << 16);
  C = (C & redblueMask) | ((C & greenMask) << 16);
  D = (D & redblueMask) | ((D & greenMask) << 16);
  
  areaA = 0x20 + xy - x - y;
  areaB = x - xy;
  areaC = y - xy;
  areaD = xy;
  
  result = ((areaA * A) + (areaB * B) + (areaC * C) + (areaD * D)) >> 5;
  
  return (result & redblueMask) | ((result >> 16) & greenMask);
}

void Scale_2xSaI (u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
		  u8 *dstPtr, u32 dstPitch, 
		  u32 dstWidth, u32 dstHeight, int width, int height)
{
  u8  *dP;
  u16 *bP;
  
  u32 w;
  u32 h;
  u32 dw;
  u32 dh;
  u32 hfinish;
  u32 wfinish;
  
  u32 Nextline = srcPitch >> 1;
  
  wfinish = (width - 1) << 16;	// convert to fixed point
  dw = wfinish / (dstWidth - 1);
  hfinish = (height - 1) << 16;	// convert to fixed point
  dh = hfinish / (dstHeight - 1);
  
  for (h = 0; h < hfinish; h += dh) {
    u32 y1, y2;
    
    y1 = h & 0xffff;	// fraction part of fixed point
    bP = (u16 *) (srcPtr + ((h >> 16) * srcPitch));
    dP = dstPtr;
    y2 = 0x10000 - y1;
    
    w = 0;
    
    for (; w < wfinish;) {
      u32 A, B, C, D;
      u32 E, F, G, H;
      u32 I, J, K, L;
      u32 x1, x2, a1, f1, f2;
      u32 position, product1;
      
      position = w >> 16;
      A = bP[position];	// current pixel
      B = bP[position + 1];	// next pixel
      C = bP[position + Nextline];
      D = bP[position + Nextline + 1];
      E = bP[position - Nextline];
      F = bP[position - Nextline + 1];
      G = bP[position - 1];
      H = bP[position + Nextline - 1];
      I = bP[position + 2];
      J = bP[position + Nextline + 2];
      K = bP[position + Nextline + Nextline];
      L = bP[position + Nextline + Nextline + 1];
      
      x1 = w & 0xffff;	// fraction part of fixed point
      x2 = 0x10000 - x1;
      
      /*0*/ 
      if (A == B && C == D && A == C)
	product1 = A;
      else /*1*/ if (A == D && B != C) {
	f1 = (x1 >> 1) + (0x10000 >> 2);
	f2 = (y1 >> 1) + (0x10000 >> 2);
	if (y1 <= f1 && A == J && A != E)	// close to B
	  {
	    a1 = f1 - y1;
	    product1 = Bilinear (A, B, a1);
	  } else if (y1 >= f1 && A == G && A != L)	// close to C
	    {
	      a1 = y1 - f1;
	      product1 = Bilinear (A, C, a1);
	    }
	else if (x1 >= f2 && A == E && A != J)	// close to B
	  {
	    a1 = x1 - f2;
	    product1 = Bilinear (A, B, a1);
	  }
	else if (x1 <= f2 && A == L && A != G)	// close to C
	  {
	    a1 = f2 - x1;
	    product1 = Bilinear (A, C, a1);
	  }
	else if (y1 >= x1)	// close to C
	  {
	    a1 = y1 - x1;
	    product1 = Bilinear (A, C, a1);
	  }
	else if (y1 <= x1)	// close to B
	  {
	    a1 = x1 - y1;
	    product1 = Bilinear (A, B, a1);
	  }
      }
      else
	/*2*/ 
	if (B == C && A != D)
	  {
	    f1 = (x1 >> 1) + (0x10000 >> 2);
	    f2 = (y1 >> 1) + (0x10000 >> 2);
	    if (y2 >= f1 && B == H && B != F)	// close to A
	      {
		a1 = y2 - f1;
		product1 = Bilinear (B, A, a1);
	      }
	    else if (y2 <= f1 && B == I && B != K)	// close to D
	      {
		a1 = f1 - y2;
		product1 = Bilinear (B, D, a1);
	      }
	    else if (x2 >= f2 && B == F && B != H)	// close to A
	      {
		a1 = x2 - f2;
		product1 = Bilinear (B, A, a1);
	      }
	    else if (x2 <= f2 && B == K && B != I)	// close to D
	      {
		a1 = f2 - x2;
		product1 = Bilinear (B, D, a1);
	      }
	    else if (y2 >= x1)	// close to A
	      {
		a1 = y2 - x1;
		product1 = Bilinear (B, A, a1);
	      }
	    else if (y2 <= x1)	// close to D
	      {
		a1 = x1 - y2;
		product1 = Bilinear (B, D, a1);
	      }
	  }
      /*3*/
	else
	  {
	    product1 = Bilinear4 (A, B, C, D, x1, y1);
	  }
      
      //end First Pixel
      *(u32 *) dP = product1;
      dP += 2;
      w += dw;
    }
    dstPtr += dstPitch;
  }
}

void palette_2xSaI(u8* srcPtr, u32 srcPitch, u8* deltaPtr, u8* dstPtr, u32 dstPitch, int width, int height, u16 palette[])
{
    for (; height; height--)
    {
        u8* bP = (u8*)srcPtr;
        u8* dP = (u8*)dstPtr;

        for (u32 finish = width; finish; finish--)
        {
            register u32 colorA, colorB;
            u32 colorC, colorD, colorE, colorF, colorG, colorH, colorI, colorJ, colorK, colorL, colorM, colorN, colorO, colorP;
            u32 product, product1, product2;

            //---------------------------------------
            // Map of the pixels:                    I|E F|J
            //                                       G|A B|K
            //                                       H|C D|L
            //                                       M|N O|P
            colorI = palette[*(bP - srcPitch - 1)];
            colorE = palette[*(bP - srcPitch)];
            colorF = palette[*(bP - srcPitch + 1)];
            colorJ = palette[*(bP - srcPitch + 2)];

            colorG = palette[*(bP - 1)];
            colorA = palette[*(bP)];
            colorB = palette[*(bP + 1)];
            colorK = palette[*(bP + 2)];

            colorH = palette[*(bP + srcPitch - 1)];
            colorC = palette[*(bP + srcPitch)];
            colorD = palette[*(bP + srcPitch + 1)];
            colorL = palette[*(bP + srcPitch + 2)];

            colorM = palette[*(bP + srcPitch + srcPitch - 1)];
            colorN = palette[*(bP + srcPitch + srcPitch)];
            colorO = palette[*(bP + srcPitch + srcPitch + 1)];
            colorP = palette[*(bP + srcPitch + srcPitch + 2)];

            if ((colorA == colorD) && (colorB != colorC))
            {
                if (((colorA == colorE) && (colorB == colorL)) || ((colorA == colorC) && (colorA == colorF) && (colorB != colorE) && (colorB == colorJ)))
                {
                    product = colorA;
                }
                else
                {
                    product = INTERPOLATE(colorA, colorB);
                }

                if (((colorA == colorG) && (colorC == colorO)) || ((colorA == colorB) && (colorA == colorH) && (colorG != colorC) && (colorC == colorM)))
                {
                    product1 = colorA;
                }
                else
                {
                    product1 = INTERPOLATE(colorA, colorC);
                }
                product2 = colorA;
            }
            else if ((colorB == colorC) && (colorA != colorD))
            {
                if (((colorB == colorF) && (colorA == colorH)) || ((colorB == colorE) && (colorB == colorD) && (colorA != colorF) && (colorA == colorI)))
                {
                    product = colorB;
                }
                else
                {
                    product = INTERPOLATE(colorA, colorB);
                }

                if (((colorC == colorH) && (colorA == colorF)) || ((colorC == colorG) && (colorC == colorD) && (colorA != colorH) && (colorA == colorI)))
                {
                    product1 = colorC;
                }
                else
                {
                    product1 = INTERPOLATE(colorA, colorC);
                }
                product2 = colorB;
            }
            else if ((colorA == colorD) && (colorB == colorC))
            {
                if (colorA == colorB)
                {
                    product = colorA;
                    product1 = colorA;
                    product2 = colorA;
                }
                else
                {
                    register int r = 0;

                    product1 = INTERPOLATE(colorA, colorC);
                    product = INTERPOLATE(colorA, colorB);

                    r += GetResult1(colorA, colorB, colorG, colorE, colorI);
                    r += GetResult2(colorB, colorA, colorK, colorF, colorJ);
                    r += GetResult2(colorB, colorA, colorH, colorN, colorM);
                    r += GetResult1(colorA, colorB, colorL, colorO, colorP);

                    if (r > 0)
                    {
                        product2 = colorA;
                    }
                    else if (r < 0)
                    {
                        product2 = colorB;
                    }
                    else
                    {
                        product2 = Q_INTERPOLATE(colorA, colorB, colorC, colorD);
                    }
                }
            }
            else
            {
                product2 = Q_INTERPOLATE(colorA, colorB, colorC, colorD);

                if ((colorA == colorC) && (colorA == colorF) && (colorB != colorE) && (colorB == colorJ))
                {
                    product = colorA;
                }
                else if ((colorB == colorE) && (colorB == colorD) && (colorA != colorF) && (colorA == colorI))
                {
                    product = colorB;
                }
                else
                {
                    product = INTERPOLATE(colorA, colorB);
                }

                if ((colorA == colorB) && (colorA == colorH) && (colorG != colorC) && (colorC == colorM))
                {
                    product1 = colorA;
                }
                else if ((colorC == colorG) && (colorC == colorD) && (colorA != colorH) && (colorA == colorI))
                {
                    product1 = colorC;
                }
                else
                {
                    product1 = INTERPOLATE(colorA, colorC);
                }
            }

            product = colorA | (product << 16);
            product1 = product1 | (product2 << 16);
            *((s32*)dP) = product;
            *((u32*)(dP + dstPitch)) = product1;

            bP++;
            dP += sizeof(u32);
        } // end of for ( finish= width etc..)

        srcPtr += srcPitch;
        dstPtr += dstPitch * 2;
        //deltaPtr += srcPitch;
    } // endof: for (height; height; height--)
}


void half_2xSaI (u8* srcPtr, u32 srcPitch, u8* deltaPtr,
	     u8* dstPtr, u32 dstPitch, int width, int height)
{
    u8  *dP;
    u16 *bP;
    u32 Nextline = srcPitch >> 1;
    
    for (; height; height--)
    {
        bP = (u16*)srcPtr;
        dP = dstPtr;
        int finish = width;
        while (--finish >= 0)
        {
        	register u32 colorA, colorB;
        	u32 colorC, colorD,
        	  colorE, colorF, colorG, colorH,
        	  colorI, colorJ, colorK, colorL;
        	u32 colorM, colorN, colorO, colorP;
        	u32 product;
        	
        	//---------------------------------------
        	// Map of the pixels:                    I|E F|J
        	//                                       G|A B|K
        	//                                       H|C D|L
        	//                                       M|N O|P
        	colorI = *(bP - Nextline - 1);
        	colorE = *(bP - Nextline);
        	colorF = *(bP - Nextline + 1);
        	colorJ = *(bP - Nextline + 2);
        	
        	colorG = *(bP - 1);
        	colorA = *(bP);
        	colorB = *(bP + 1);
        	colorK = *(bP + 2);
        	
        	colorH = *(bP + Nextline - 1);
        	colorC = *(bP + Nextline);
        	colorD = *(bP + Nextline + 1);
        	colorL = *(bP + Nextline + 2);
        	
        	if (finish == 0)
        	{
        	    colorB = colorA;
        	}
        	
        	//colorM = *(bP + Nextline + Nextline - 1);
        	//colorN = *(bP + Nextline + Nextline);
        	//colorO = *(bP + Nextline + Nextline + 1);
        	//colorP = *(bP + Nextline + Nextline + 2);
        	
        	if ((colorA == colorD) && (colorB != colorC)) {
        	  if (((colorA == colorE) && (colorB == colorL)) ||
        	      ((colorA == colorC) && (colorA == colorF)
        	       && (colorB != colorE) && (colorB == colorJ))) {
        	    product = colorA;
        	  } else {
        	    product = INTERPOLATE (colorA, colorB);
        	  }
        	} else if ((colorB == colorC) && (colorA != colorD)) {
        	  if (((colorB == colorF) && (colorA == colorH)) ||
        	      ((colorB == colorE) && (colorB == colorD)
        	       && (colorA != colorF) && (colorA == colorI))) {
        	    product = colorB;
        	  } else {
        	    product = INTERPOLATE (colorA, colorB);
        	  }
        	} else if ((colorA == colorD) && (colorB == colorC)) {
        	  if (colorA == colorB) {
        	    product = colorA;
        	  } else {
        	    product = INTERPOLATE (colorA, colorB);
        	  }
        	} else {
        	  if ((colorA == colorC) && (colorA == colorF)
        	      && (colorB != colorE) && (colorB == colorJ)) {
        	    product = colorA;
        	  } else if ((colorB == colorE) && (colorB == colorD)
        		     && (colorA != colorF) && (colorA == colorI)) {
        	    product = colorB;
        	  } else {
        	    product = INTERPOLATE (colorA, colorB);
        	  }
        	}
        	
        	product = colorA | (product << 16);
        	*((s32 *) dP) = product;
        	
        	bP++;
        	dP += sizeof (u32);
        }			// end of for ( finish= width etc..)
      
      srcPtr += srcPitch;
      dstPtr += dstPitch;
      //dstPtr += dstPitch * 2;
//      deltaPtr += srcPitch;
    }			// endof: for (height; height; height--)
}